/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.constant.CommonConstant;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.constant.enums.IsfdModelManagementBoundarySaveTypeEnum;
import com.comac.ins.isfd.domain.IsfdModelManagementBoundary;
import com.comac.ins.isfd.domain.IsfdModelManagementCalculateRefBoundary;
import com.comac.ins.isfd.domain.bo.IsfdModelManagementBoundaryBo;
import com.comac.ins.isfd.domain.bo.query.IsfdModelManagementBoundaryQueryBo;
import com.comac.ins.isfd.domain.vo.IsfdModelManagementBoundaryVo;
import com.comac.ins.isfd.domain.vo.IsfdModelManagementCalculateFileVo;
import com.comac.ins.isfd.domain.vo.IsfdModelManagementStructureDefinitionTreeVo;
import com.comac.ins.isfd.domain.vo.IsfdModelManagementTaskVo;
import com.comac.ins.isfd.mapper.IsfdModelManagementBoundaryMapper;
import com.comac.ins.isfd.mapper.IsfdModelManagementCalculateFileMapper;
import com.comac.ins.isfd.mapper.IsfdModelManagementCalculateRefBoundaryMapper;
import com.comac.ins.isfd.mapper.IsfdModelManagementTaskMapper;
import com.comac.ins.isfd.service.IIsfdModelManagementBoundaryService;
import com.comac.ins.isfd.service.IIsfdModelManagementStructureDefinitionTreeService;
import com.comac.ins.system.service.ISysDictDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 模型管理边界条件Service业务层处理
 *
 * @author Lion Li
 * @date 2024-08-19
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class IsfdModelManagementBoundaryServiceImpl implements IIsfdModelManagementBoundaryService {

    @Autowired
    private IsfdModelManagementBoundaryMapper baseMapper;
    @Autowired
    private IsfdModelManagementCalculateRefBoundaryMapper isfdModelManagementCalculateRefBoundaryMapper;
    @Autowired
    private IsfdModelManagementCalculateFileMapper isfdModelManagementCalculateFileMapper;
    @Autowired
    private IsfdModelManagementTaskMapper isfdModelManagementTaskMapper;
    @Autowired
    private IIsfdModelManagementStructureDefinitionTreeService iIsfdModelManagementStructureDefinitionTreeService;
    @Autowired
    private ISysDictDataService iSysDictDataService;

    /**
     * 查询模型管理边界条件
     *
     * @param id 主键
     * @return 模型管理边界条件
     */
    @Override
    public IsfdModelManagementBoundaryVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }


    @Override
    public TableDataInfo<IsfdModelManagementBoundaryVo> queryPageList(IsfdModelManagementBoundaryQueryBo bo) {
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(bo.getPageNum());
        pageQuery.setPageSize(bo.getPageSize());
        LambdaQueryWrapper<IsfdModelManagementBoundary> lqw = buildQueryWrapper(bo);
        Page<IsfdModelManagementBoundaryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        result.getRecords().forEach(s -> {
            s.setModelName(s.getModelNumber());

            IsfdModelManagementStructureDefinitionTreeVo batchVo = iIsfdModelManagementStructureDefinitionTreeService.queryOneByQueryIndex(s.getModelNumber(), s.getBatchNumber(), null);
            s.setBatchName(batchVo != null ? batchVo.getName() : null);
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的模型管理边界条件列表
     *
     * @param bo 查询条件
     * @return 模型管理边界条件列表
     */
    @Override
    public List<IsfdModelManagementBoundaryVo> queryList(IsfdModelManagementBoundaryBo bo) {
        LambdaQueryWrapper<IsfdModelManagementBoundary> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<IsfdModelManagementBoundaryVo> queryListByCalculateId(Long calculateId) {
        List<IsfdModelManagementCalculateRefBoundary> isfdModelManagementCalculateRefBoundaries = isfdModelManagementCalculateRefBoundaryMapper
            .selectList(new LambdaQueryWrapper<IsfdModelManagementCalculateRefBoundary>()
                .eq(IsfdModelManagementCalculateRefBoundary::getCalculateId, calculateId));
        if (CollectionUtils.isEmpty(isfdModelManagementCalculateRefBoundaries)) {
            return new ArrayList<>();
        }
        List<Long> boundaryIds = isfdModelManagementCalculateRefBoundaries.stream().map(IsfdModelManagementCalculateRefBoundary::getBoundaryId).toList();
        List<IsfdModelManagementBoundaryVo> boundaryVoList = baseMapper.selectVoBatchIds(boundaryIds);
        boundaryVoList.forEach(boundaryVo -> {
            IsfdModelManagementStructureDefinitionTreeVo batchVo = iIsfdModelManagementStructureDefinitionTreeService.queryOneByQueryIndex(boundaryVo.getModelNumber(), boundaryVo.getBatchNumber(), null);
            boundaryVo.setBatchName(batchVo != null ? batchVo.getName() : null);
        });
        return boundaryVoList;
    }

    private LambdaQueryWrapper<IsfdModelManagementBoundary> buildQueryWrapper(IsfdModelManagementBoundaryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IsfdModelManagementBoundary> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getFileName()), IsfdModelManagementBoundary::getFileName, bo.getFileName());
        lqw.eq(bo.getFileSize() != null, IsfdModelManagementBoundary::getFileSize, bo.getFileSize());
        lqw.eq(StringUtils.isNotBlank(bo.getFileUrl()), IsfdModelManagementBoundary::getFileUrl, bo.getFileUrl());
        lqw.eq(bo.getModelNumber() != null, IsfdModelManagementBoundary::getModelNumber, bo.getModelNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getBatchNumber()), IsfdModelManagementBoundary::getBatchNumber, bo.getBatchNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), IsfdModelManagementBoundary::getRemarks, bo.getRemarks());
        return lqw;
    }


    private LambdaQueryWrapper<IsfdModelManagementBoundary> buildQueryWrapper(IsfdModelManagementBoundaryQueryBo bo) {
        LambdaQueryWrapper<IsfdModelManagementBoundary> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getModelNumber()), IsfdModelManagementBoundary::getModelNumber, bo.getModelNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getBatchNumber()), IsfdModelManagementBoundary::getBatchNumber, bo.getBatchNumber());
        lqw.like(StringUtils.isNotBlank(bo.getFileName()), IsfdModelManagementBoundary::getFileName, bo.getFileName());
        lqw.like(StringUtils.isNotBlank(bo.getRemarks()), IsfdModelManagementBoundary::getRemarks, bo.getRemarks());
        lqw.orderByDesc(IsfdModelManagementBoundary::getCreateTime);
        return lqw;
    }

    /**
     * 新增模型管理边界条件
     *
     * @param bo 模型管理边界条件
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(IsfdModelManagementBoundaryBo bo) {
        IsfdModelManagementBoundary add = MapstructUtils.convert(bo, IsfdModelManagementBoundary.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改模型管理边界条件
     *
     * @param bo 模型管理边界条件
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(IsfdModelManagementBoundaryBo bo) {
        IsfdModelManagementBoundary update = MapstructUtils.convert(bo, IsfdModelManagementBoundary.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public Boolean save(MultipartFile multipartFile, Long id, String type, String modelNumber, String remarks, String batchNumbers) {
        // 1.查询机型
        IsfdModelManagementStructureDefinitionTreeVo modelVo = iIsfdModelManagementStructureDefinitionTreeService.queryOneByQueryIndex(modelNumber, null, null);
        if (modelVo == null) {
            throw new BaseException("选择的机型不存在，请确认后重试.");
        }
        String prefixPath = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE,
            CommonConstant.MODEL_MANAGEMENT_BOUNDARY_DATA_PREFIX);
        if (StringUtils.isBlank(prefixPath)) {
            throw new BaseException("边界条件存储路径前缀未配置，请到字典管理中配置，并重试.");
        }
        List<String> batchNumberList = StringUtils.splitList(batchNumbers, ",");
        if (IsfdModelManagementBoundarySaveTypeEnum.ADD.getValue().equals(type)) {
            batchNumberList.forEach(batchNumber -> {
                try {
                    String fileName = multipartFile.getOriginalFilename();
                    String filePath = prefixPath + batchNumber + '/' + System.currentTimeMillis();
                    String fileUrl = filePath + "/" + fileName;
                    Path targetPath = Paths.get(fileUrl);
                    File dir = targetPath.getParent().toFile();
                    if (!dir.exists()) {
                        dir.mkdirs();
                    }
                    Files.write(targetPath, multipartFile.getBytes());
                    IsfdModelManagementBoundary po = new IsfdModelManagementBoundary();
                    po.setModelNumber(modelNumber);
                    po.setFileName(fileName);
                    // 保留5位小数
                    String resultStr = String.format("%.5f", (double) multipartFile.getSize() / 1024);
                    po.setFileSize(Double.parseDouble(resultStr));
                    po.setFileUrl(fileUrl);
                    po.setRemarks(remarks);
                    po.setBatchNumber(batchNumber);
                    baseMapper.insert(po);
                } catch (Exception e) {
                    log.error("边界条件新增失败", e);
                    throw new BaseException("边界条件新增失败");
                }
            });
        } else if (IsfdModelManagementBoundarySaveTypeEnum.COPY.getValue().equals(type)) {
            IsfdModelManagementBoundaryVo isfdModelManagementBoundaryVo = baseMapper.selectVoById(id);
            if(isfdModelManagementBoundaryVo  == null){
                throw new BaseException("边界条件复制保存失败，当前复制的数据不存在！");
            }
            String fileName = isfdModelManagementBoundaryVo.getFileName();
            Double fileSize = isfdModelManagementBoundaryVo.getFileSize();
            String fileUrl = isfdModelManagementBoundaryVo.getFileUrl();
            batchNumberList.forEach(batchNumber -> {
                IsfdModelManagementBoundary po = new IsfdModelManagementBoundary();
                po.setModelNumber(modelNumber);
                po.setBatchNumber(batchNumber);
                po.setFileName(fileName);
                po.setFileSize(fileSize);
                po.setFileUrl(fileUrl);
                po.setRemarks(remarks);
                baseMapper.insert(po);
            });
        } else {
            throw new BaseException("保存的type类型不存在，请确认后重试！");
        }
        return Boolean.TRUE;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IsfdModelManagementBoundary entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除边界条件信息
     *
     * @param ids 待删除的主键集合
     * @return 是否删除成功
     */
    @Transactional
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        for (Long id : ids) {
            // 删除主表
            baseMapper.deleteById(id);
            // 删除和计算的关联关系表
            isfdModelManagementCalculateRefBoundaryMapper.delete(new LambdaQueryWrapper<IsfdModelManagementCalculateRefBoundary>()
                .eq(IsfdModelManagementCalculateRefBoundary::getBoundaryId, id));
        }
        return Boolean.TRUE;
    }

    @Override
    public String preDelete(Collection<Long> ids) {
        String result = null;
        for (Long id : ids) {
            // 查主表
            IsfdModelManagementBoundary isfdModelManagementBoundary = baseMapper.selectById(id);
            // 查询和计算的关联关系表
            List<IsfdModelManagementCalculateRefBoundary> isfdModelManagementCalculateRefBoundaries = isfdModelManagementCalculateRefBoundaryMapper.selectList(new LambdaQueryWrapper<IsfdModelManagementCalculateRefBoundary>()
                .eq(IsfdModelManagementCalculateRefBoundary::getBoundaryId, id));
            if (CollectionUtils.isNotEmpty(isfdModelManagementCalculateRefBoundaries)) {
                for (IsfdModelManagementCalculateRefBoundary isfdModelManagementCalculateRefBoundary : isfdModelManagementCalculateRefBoundaries) {
                    IsfdModelManagementCalculateFileVo isfdModelManagementCalculateFileVo = isfdModelManagementCalculateFileMapper.selectVoById(isfdModelManagementCalculateRefBoundary.getCalculateId());
                    if (isfdModelManagementCalculateFileVo == null) {
                        continue;
                    }
                    IsfdModelManagementTaskVo isfdModelManagementTaskVo = isfdModelManagementTaskMapper.selectVoById(isfdModelManagementCalculateFileVo.getTaskId());
                    if (isfdModelManagementTaskVo == null) {
                        continue;
                    }
                    String taskName = isfdModelManagementTaskVo.getTaskName();
                    result = "文件名为：" + isfdModelManagementBoundary.getFileName() + "的边界条件，至少和模型组建任务为:" + taskName + "的计算存在关联关系，确认是否删除？";
                    break;
                }
            }
        }
        return result;
    }

    /**
     * 批量查询边界条件数据
     *
     * @param ids
     * @return
     */
    @Override
    public List<IsfdModelManagementBoundaryVo> queryByBatchIds(List<Long> ids) {
        return baseMapper.selectVoBatchIds(ids);
    }
}
